package me.itsoo.artemis.framework.repository.config;

import lombok.Data;
import me.itsoo.artemis.framework.core.env.Environment;
import me.itsoo.artemis.framework.core.util.NumberUtils;
import me.itsoo.artemis.framework.core.util.StringUtils;
import me.itsoo.artemis.framework.repository.datasource.ConnectionPool;
import me.itsoo.artemis.framework.repository.datasource.DataSourceManager;
import me.itsoo.artemis.framework.repository.executor.SqlExecutor;
import me.itsoo.artemis.framework.repository.interceptor.SqlInterceptor;
import me.itsoo.artemis.framework.repository.mapper.DefaultSqlMapper;
import me.itsoo.artemis.framework.repository.mapper.SqlMapper;
import me.itsoo.artemis.framework.repository.mapper.SqlMapperFactory;

import java.util.Collection;
import java.util.Map;
import java.util.Properties;

/**
 * 核心配置对象：通过重量级对象实现执行链路的整体隔离
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/5/17
 */
@Data
@SuppressWarnings({"unchecked", "rawtypes"})
public class Configuration implements SqlConfigurable {

    /**
     * 【默认】核心连接数
     */
    public static final int DEFAULT_CORE_SIZE = 10;

    /**
     * 【默认】最大连接数
     */
    public static final int DEFAULT_MAX_SIZE = 20;

    /**
     * 【默认】最大等待连接时间（指获取连接动作）
     */
    public static final int DEFAULT_MAX_WAIT = 100;

    /**
     * 【默认】连接保活时间（秒）
     */
    public static final int DEFAULT_KEEP_ALIVE = 60;

    /**
     * 环境配置
     */
    private final Environment env;

    /**
     * Cached SqlMapper mapping
     */
    private Map<Class<SqlMapper>, SqlMapper> sqlMapperCache;

    /**
     * Default SqlExecutor
     */
    private SqlExecutor sqlExecutor;

    /**
     * All SqlInterceptor
     */
    private Collection<SqlInterceptor> sqlInterceptors;

    /**
     * Default DataSource
     */
    private final ConnectionPool dataSource;

    public Configuration(Properties prop) {
        this(Environment.createAppProperties(prop));
    }

    public Configuration(Environment env) {
        this.env = env;
        this.dataSource = new DataSourceManager(this);
    }

    @Override
    public Configuration getConfig() {
        return this;
    }

    /**
     * 设置 SqlMapper 缓存
     *
     * @param sqlMapperCache Map
     */
    public void setSqlMapperCache(Map<Class<SqlMapper>, SqlMapper> sqlMapperCache) {
        this.sqlMapperCache = sqlMapperCache;
    }

    /**
     * 获取 SqlMapper
     *
     * @param mapperType Class
     * @param <T>        T
     * @return T
     */
    public <T extends SqlMapper> T getSqlMapper(Class<T> mapperType) {
        return (T) sqlMapperCache.get(mapperType);
    }

    /**
     * 获取 DefaultSqlMapper
     *
     * @param dataType Class
     * @param <T>      T
     * @return DefaultSqlMapper
     */
    public <T> DefaultSqlMapper<T> getDefaultSqlMapper(Class<T> dataType) {
        return SqlMapperFactory.getDefaultSqlMapper(dataType, this);
    }

    /**
     * 获取扫描根路径
     *
     * @return String
     */
    public String getScannerBasePackage() {
        return StringUtils.defaultIfBlank(env.getProperty("afr.scanner.base-package"), "");
    }

    /**
     * 数据库驱动
     *
     * @return String
     */
    public String getDriverClassName() {
        return env.getProperty("afr.datasource.driver-class-name");
    }

    /**
     * 数据库连接 URL
     *
     * @return String
     */
    public String getUrl() {
        return env.getProperty("afr.datasource.url");
    }

    /**
     * 数据库连接用户名
     *
     * @return String
     */
    public String getUsername() {
        return env.getProperty("afr.datasource.username");
    }

    /**
     * 数据库连接密码
     *
     * @return String
     */
    public String getPassword() {
        return env.getProperty("afr.datasource.password");
    }

    /**
     * 核心连接数
     *
     * @return int
     */
    public int getCoreSize() {
        return NumberUtils.parseInt(getValueOrDefault("afr.datasource.core-size", DEFAULT_CORE_SIZE));
    }

    /**
     * 最大连接数
     *
     * @return int
     */
    public int getMaxSize() {
        return NumberUtils.parseInt(getValueOrDefault("afr.datasource.max-size", DEFAULT_MAX_SIZE));
    }

    /**
     * 最大等待连接时间（毫秒）
     *
     * @return int
     */
    public int getMaxWait() {
        return NumberUtils.parseInt(getValueOrDefault("afr.datasource.max-wait", DEFAULT_MAX_WAIT));
    }

    /**
     * 连接保活时间（秒）
     *
     * @return int
     */
    public int getKeepAlive() {
        return NumberUtils.parseInt(getValueOrDefault("afr.datasource.keep-alive", DEFAULT_KEEP_ALIVE));
    }

    /**
     * 连接保活 SQL
     *
     * @return String
     */
    public String getValidationQuery() {
        return getValueOrDefault("afr.datasource.validation-query", null);
    }

    /**
     * 获取配置值，提供默认可选
     *
     * @param key        String
     * @param defaultVal String
     * @return String
     */
    private String getValueOrDefault(String key, int defaultVal) {
        return getValueOrDefault(env.getProperty(key), String.valueOf(defaultVal));
    }

    /**
     * 获取配置值，提供默认可选
     *
     * @param value      String
     * @param defaultVal String
     * @return String
     */
    private String getValueOrDefault(String value, String defaultVal) {
        return StringUtils.defaultIfBlank(value, defaultVal);
    }
}
